﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ObviousCode.UI.Aspect.PluginLibrary.Interfaces;
using ObviousCode.Aspect.PluginLibrary.Interfaces;
using ObviousCode.UI.Aspect.PluginLibrary;
using ObviousCode.Common.Utils.Library.Exceptions;
using ObviousCode.Common.Utils.Library.Dictionaries;
using ObviousCode.Aspect.PluginLibrary.Caches;

namespace ObviousCode.Aspect.PluginLibrary.Abstract
{
    public abstract class BaseSurfaceObjectFactory<TSurfaceObjectInstanceType> 
        : ISurfaceObjectFactory<TSurfaceObjectInstanceType> where TSurfaceObjectInstanceType : ISurfaceObject
    {
        SurfaceItemDescriptorStore _store;

        public BaseSurfaceObjectFactory(IAspectDesigner host)
        {
            Host = host;

            Properties = new PropertyDictionary();

            _store = new SurfaceItemDescriptorStore();
        }

        public virtual void Setup()
        {
        
        }

        public virtual void TearDown()
        {

        }

        public bool ContainsKey(string key)
        {
            return _store.ContainsKey(key);
        }

        public virtual ISurfaceObject BuildObject(Type type)
        {
            return BuildObject(GetDescriptorContainingAspectItemFactoryFor(type).Key);
        }

        public virtual ISurfaceObject BuildObject(string key)
        {
            if (!_store.ContainsKey(key)) ExceptionBuilder.Format("Key \"{0}\" not located in {1}.", key, GetType().ToString());

            IAspectItem tag = _store[key].Factory.CreateInstance(new object[] { });

            ISurfaceObject item = BuildNewItem();

            item.Tag = tag;            

            item.Images = _store[key].Images;
            item.Theme = _store[key].Theme;

            AspectCache.Main.SetSurfaceObject(item);
            AspectCache.Main.SetAspectItem(tag);

            return item;
        }

        protected abstract TSurfaceObjectInstanceType BuildNewItem();
                
        public void RegisterSurfaceItemDescriptor(string key, SurfaceItemDescriptor descriptor)
        {            
            _store[key] = descriptor;
        }

        public void RegisterUITheme(string key, IUITheme theme)
        {
            _store[key].Theme = theme;
        }

        public void RegisterImages(string key, ChartObjectImages images)
        {
            _store[key].Images = images;
        }

        public void RegisterItemBuilderCallback(string key, IAspectItemFactory factory)
        {
            _store[key].Factory = factory;
        }

        public void RegisterDescription(string key, string description)
        {
            _store[key].Description = description;
        }

        public IEnumerable<string> AvailableItemKeys { get { return _store.Keys; } }

        public SurfaceItemDescriptor this[string key]
        {
            get
            {
                return _store[key];
            }
        }

        protected IAspectDesigner Host { get; private set; }

        public ObviousCode.Common.Utils.Library.Dictionaries.PropertyDictionary Properties { get; private set; }

        public bool ContainsAspectItemFactory(Type type)
        {
            return GetDescriptorContainingAspectItemFactoryFor(type) != null;
        }

        public SurfaceItemDescriptor GetDescriptorContainingAspectItemFactoryFor(Type type)
        {
            return _store.For(type);
        }

        public Type InstanceType { get { return typeof(TSurfaceObjectInstanceType); } }
    }
}
